﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Transactions;
using System.Data.SqlClient;

    public partial class GSG_importacaoSeman_ImportacaoMxmSeman : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                
            }

			//Verificando o login do usuário
            if (Session["chapa"] == null)
            {
                Response.Redirect("../mensagens_sistema.aspx?id_mensagem=2");
            }
            else if (!Session["lotacao"].ToString().Equals("GSI-Coord. de Logística e Manutenção") && !Session["Conta_Master"].ToString().Equals("True"))
            {
                Response.Redirect("../mensagens_sistema.aspx?id_mensagem=2");
            }
        }

        //Colocar dentro do web.config dentro da tag <system.web> => <httpRuntime maxRequestLength="2048"/> 2Mb
        /// <summary>
        /// Método principal, responsável por chamar os demais métodos e realizar a atividade de importação como um todo
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Importar_Click(object sender, EventArgs e)
        {
            string caminho = Server.MapPath(@"tempUploadMxmSeman\");

            if (!Directory.Exists(caminho))
                Directory.CreateDirectory(caminho);

            //Extensões permitidas para validar arquivo
            List<string> listExtensao = new List<string>() { ".xls", ".xlsx" };

            string caminhoComArquivo = string.Empty;
            
            Negocio neg = new Negocio();

            if (this.FileUpload1.HasFile)
            {
                double tamanhoArquivo = this.FileUpload1.FileBytes.Length;
                
                //Conversão para tamanho máximo do arquivo 2Mb
                double calculo = (tamanhoArquivo / 1024) / 1024;
                
                //Verificando se o arquivo é maior ou menor que 2Mb
                if (calculo > 2)
                {
                    MensagemTela("O tamanho do arquivo selecionado excede o limite máximo permitido!");
                }
                else
                {
                    caminhoComArquivo = caminho + FileUpload1.FileName;

                    try
                    {
                        //Verificando se a extensão do arquivo selecionado, está na lista de extensões permitidas
                        if (listExtensao.Contains(System.IO.Path.GetExtension(FileUpload1.FileName)))
                        {
                            //Salvando o arquivo no caminho especificado
                            FileUpload1.SaveAs(caminhoComArquivo);

                            DataTable dt = new DataTable();

                            //Definindo a string de conexão para o excel
                            if (System.IO.Path.GetExtension(FileUpload1.FileName).Equals(".xls"))
                                dt = neg.LerExcel(caminhoComArquivo, enumTipoExcel.Excel97_2003);
                            else if (System.IO.Path.GetExtension(FileUpload1.FileName).Equals(".xlsx"))
                                dt = neg.LerExcel(caminhoComArquivo, enumTipoExcel.Excel2007_2013);

                            //Validando o "excel" através dos dados num DataTable
                            if (neg.ValidarExcelMXM(dt))
                            {
                                //Capturar todos os equipamentos do "excel"
                                List<Equipamento> listEquipamento = neg.ListarEquipamentos(dt);

                                //Verificando se existe algum equipamento registrado no "excel"
                                if (listEquipamento != null)
                                {
                                    //Capturar todos os locais que não estão cadastrados no banco
                                    List<string> listLocaisInexistentes = neg.VerificarLocais();

                                    //Verificando se foi encontrado algum local inexistente
                                    if (listLocaisInexistentes.Count > 0)
                                    {
                                        //Criando string para ser exibida na tela com todos os locais inexistentes
                                        string locais = MontarDadosMensagem(listLocaisInexistentes);
                                        MensagemTela("Locais não estão cadastrados --> " + locais.Remove(locais.Length - 3, 3));
                                    }
                                    else
                                    {
                                        //Capturar todos os Grupos ou Subgrupos inexistente
                                        List<string> listGruposSubgruposInexistentes = neg.VerificarGruposESubgrupos();

                                        //Verificando se foi encontrado algum grupo ou subgrupo inexistente
                                        if (listGruposSubgruposInexistentes.Count > 0)
                                        {
                                            //Criando string para ser exibida na tela com todos os grupos ou subgrupos inexistentes
                                            string grupSub = MontarDadosMensagem(listGruposSubgruposInexistentes);
                                            MensagemTela("Grupos/Subgrupos não estão cadastrados --> " + grupSub.Remove(grupSub.Length - 3, 3));
                                        }
                                        else
                                        {
                                            //Capturar os equipamentos que já existem cadastrados no banco de dados
                                            List<string> listEquipamentosInexistentes = neg.VerificarExistenciaEquipamentos(listEquipamento);
                                            
                                            //Verificando se foi encontrado algum equipamento
                                            if (listEquipamentosInexistentes.Count > 0)
                                            {
                                                //Criando string para ser exibida na tela com todos os equipamentos que já existem cadastrados
                                                string equipNaoExistentes = MontarDadosMensagem(listEquipamentosInexistentes);
                                                MensagemTela("Euipamentos já cadastrados --> " + equipNaoExistentes.Remove(equipNaoExistentes.Length -3, 3));
                                            }
                                            else
                                            {
                                                //Inserindo os equipamentos no banco de dados
                                                neg.InserirNaBase(listEquipamento, Session["nome"].ToString());

                                                MensagemTela("Arquivo importado com sucesso! Total de Equipamentos importados: " + listEquipamento.Count.ToString());
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    MensagemTela("Não foram encontrados equipamentos no arquivo excel.");
                                }
                            }
                            else
                            {
                                MensagemTela("Excel não válido!");
                            }
                        }
                        else
                        {
                            MensagemTela("Arquivo com formato inválido!");
                        }

                    }
                    catch (Exception exc)
                    {
                        MensagemTela(exc.Message);
                    }
                    finally
                    {
                        //Apaga o arquivo que foi salvo no servidor
                        if (File.Exists(caminhoComArquivo))
                            File.Delete(caminhoComArquivo);
                    }
                }
            }
            else
            {
                MensagemTela("Não existe arquivo selecionado!");
            }
        }

        /// <summary>
        /// Método utilizado para retornar todo o conteúdo de uma lista em uma única string
        /// </summary>
        /// <param name="listObjeto">Lista com todos os dados necessários</param>
        /// <returns>Única variável do tipo string com todo o conteúdo da list dentro</returns>
        private string MontarDadosMensagem(List<string> listObjeto)
        {
            string resultado = "";
            foreach (string item in listObjeto)
            {
                resultado += item + " | ";
            }

            return resultado;
        }

        /// <summary>
        /// Método para exibir mensagem na tela.
        /// </summary>
        /// <param name="mensagem">Mensagem que será exibida na tela</param>
        private void MensagemTela(string mensagem)
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), "alert('" + mensagem.Replace("'", "") + "');", true);
        }

    }

    public enum enumTipoExcel
    {
        Excel97_2003,
        Excel2007_2013
    }



    public class Equipamento
    {
        public string Codigo { get; set; }
        public string Descricao { get; set; }
        public string Local { get; set; }
        public string Tipo { get; set; }
    }



    public class Negocio
    {
        public static List<string> listLocais { get; set; }
        public static List<string> listGrupos { get; set; }
        public static List<string> listGruposSubgrupos { get; set; }
        
        /// <summary>
        /// Responsável por verificar se o excel está com o cabeçalho padronizado.
        /// </summary>
        /// <param name="dt">Datatable com o conteúdo do excel</param>
        /// <returns>Booleana com resultado</returns>
        public bool ValidarExcelMXM(DataTable dt)
        {
            try
            {
                if (dt.Rows[0][0].ToString().Equals("Período:"))
                {
                    if (dt.Rows[1][0].ToString().Equals("Aquisição:") && dt.Rows[1][5].ToString().Equals("Saldo dos Itens Patrimoniais (R$)"))
                    {
                        if (dt.Rows[2][0].ToString().Equals("Empresa"))
                        {
                            string strHora = dt.Rows[2][12].ToString();
                            string strData = dt.Rows[2][14].ToString();

                            if (strHora.Contains("Hora:") && strData.Contains("Data:"))
                                return true;
                        }
                    }
                }
                return false;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Responsável por realizar a leitura do excel e colocar os seus dados num datatable
        /// </summary>
        /// <param name="caminho">Caminho aonde o arquivo se encontra</param>
        /// <param name="tipo">Qual a versão do excel</param>
        /// <returns>Datatable com os registros contidos no excel</returns>
        public DataTable LerExcel(string caminho, enumTipoExcel tipo)
        {
            string strConexao = string.Empty;

            //Verificando qual versão do excel será utilizada
            switch (tipo)
            {
                case enumTipoExcel.Excel97_2003:
                    strConexao = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + caminho + ";Extended Properties=\"Excel 8.0;HDR=NO\";";
                    break;
                case enumTipoExcel.Excel2007_2013:
                    strConexao = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + caminho + ";Extended Properties=\"Excel 12.0;HDR=NO\";";
                    break;
            }

            OleDbConnection conexao = null;
            DataSet ds = null;

            try
            {
                //Abrindo conexão com excel e jogando seu conteúdo para um dataset
                conexao = new OleDbConnection(strConexao);
                OleDbDataAdapter adapter = new OleDbDataAdapter("select * from [MXM$]", conexao);
                ds = new DataSet();
                conexao.Open();
                adapter.Fill(ds);
            }
            catch
            {
                throw;
            }
            finally
            {
                conexao.Close();
            }

            return ds.Tables[0];
        }

        /// <summary>
        /// Responsável por percorrer o datatable e armazenar todas as informações referentes aos equipamentos numa
        /// lista tipada que servirá de retorno do método. Também armazena os Locais, Grupos e Subgrupos em suas respectivas listas 
        /// para uma verificação da existência dos mesmos no banco.
        /// </summary>
        /// <param name="dt">Datatable com todos os registros refentes aos equipamentos</param>
        /// <returns>Lista tipada com todas as informações necessárias contidas no datatable</returns>
        public List<Equipamento> ListarEquipamentos(DataTable dt)
        {
            List<Equipamento> listEquipamento = new List<Equipamento>();
            listLocais = new List<string>();
            listGrupos = new List<string>();
            listGruposSubgrupos = new List<string>();

            try
            {
                for (int i = 5; i < dt.Rows.Count; i++)
                {
                    Equipamento equip = new Equipamento();

                    string conteudo = dt.Rows[i][0].ToString().ToLower();

                    float num = new float();
                    if (float.TryParse(conteudo, out num))
                    {
                        equip.Codigo = conteudo;
                        equip.Descricao = dt.Rows[i][2].ToString();

                        i++;
                        num = new float();
                        while (!float.TryParse(dt.Rows[i][0].ToString(), out num))
                        {
                            if (!dt.Rows[i][0].ToString().Equals("GSG"))
                            {
                                if (i < dt.Rows.Count)
                                {
                                    i++;
                                }
                                else
                                    break;
                            }
                            else
                                break;
                        }

                        equip.Local = dt.Rows[i][0].ToString();
                        equip.Tipo = dt.Rows[i][1].ToString() + "." + dt.Rows[i][2].ToString();
                        listEquipamento.Add(equip);

                        //Armazenando Locais para verificação no banco
                        if (!listLocais.Contains(equip.Local))
                            listLocais.Add(equip.Local);

                        //Armazenando apenas os Grupo
                        if (!listGrupos.Contains(dt.Rows[i][1].ToString()))
                            listGrupos.Add(dt.Rows[i][1].ToString());

                        //Armazenando Grupos Com respectivos Subgrupos
                        if (!listGruposSubgrupos.Contains(equip.Tipo))
                            listGruposSubgrupos.Add(equip.Tipo);
                    }
                }
            }
            catch
            {
                throw;
            }

            return listEquipamento;
        }

        public List<string> VerificarExistenciaEquipamentos(List<Equipamento> listEquipamentos)
        {
            return Dao.Instance.VerificandoExistenciaEquipamentos(listEquipamentos);
        }

        public List<string> VerificarLocais()
        {
            return Dao.Instance.VerificandoLocais(listLocais);
        }

        public List<string> VerificarGruposESubgrupos()
        {
            return Dao.Instance.VerificandoGruposESubgrupos(listGrupos, listGruposSubgrupos);
        }

        public void InserirNaBase(List<Equipamento> listEquipamento, string usuario)
        {
            Dao.Instance.InserindoNaBase(listEquipamento, usuario);
        }

    }



    public class Dao
    {
        #region Singleton
        private static Dao instance;

        private Dao() { }

        public static Dao Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Dao();
                }
                return instance;
            }
        }
        #endregion

        /// <summary>
        /// Responsável por retornar a string de conexão com o banco
        /// </summary>
        private string strConn
        {
            get { return @"Data Source=sqlfolha;Password=#useman#;User ID=useman;Initial Catalog=Seman"; }
            //get { return @"Data Source=sqlfolha;Password=#useman#;User ID=useman;Initial Catalog=SemanBkp"; }
            //get { return @"Data Source=SQLFOLHA;Initial Catalog=SemanBkp;Persist Security Info=True;User ID=rm_ler;Password=rm_ler9405"; }  
            //get { return @"Data Source=SQLFOLHA;Database=SemanBkp;Trusted_Connection=True;"; }  
        }

        public List<string> VerificandoLocais(List<string> listLocais)
        {
            return realizandoVerificacoes("local_equipamento", "cod_local_equipamento", listLocais, null);
        }

        public List<string> VerificandoGruposESubgrupos(List<string> listGrupos, List<string> listGruposSubgrupos)
        {
            List<string> listInexistentes = new List<string>();

            if (listGrupos.Count > 0)
            {
                listInexistentes = realizandoVerificacoes("tipo_equipamento", "cod_tipo_equipamento", listGrupos, null);
            }

            if (listInexistentes.Count == 0)
            {
                listInexistentes = realizandoVerificacoes("tipo_equipamento", "cod_tipo_equipamento", listGruposSubgrupos, null);
            }

            return listInexistentes;
        }

        private List<string> realizandoVerificacoes(string tabela, string coluna, List<string> listaVerificar, List<Equipamento> listaVerificarEquip)
        {
            string consulta = "SELECT " + coluna + " FROM " + tabela + " WHERE " + coluna + " IN (";
 
            List<string> listInexistentes = new List<string>();
            StringBuilder sb = new StringBuilder();
            sb.Append(consulta);

            try
            {
                if (listaVerificar != null)
                {
                    foreach (string item in listaVerificar)
                    {
                        sb.Append("'" + item + "',");
                    }
                }
                else if (listaVerificarEquip != null)
                {
                    foreach (Equipamento equip in listaVerificarEquip)
                    {
                        sb.Append("'" + equip.Codigo + "',");
                    }
                }

                DataTable dt = executarQuery(sb.ToString().Remove(sb.Length - 1, 1) + ");");

                if (dt != null && dt.Rows.Count > 0)
                {
                    if (listaVerificar != null)
                    {
                        foreach (string item in listaVerificar)
                        {
                            if ((dt.Select("" + coluna + " = '" + item + "'")).Length == 0)
                            {
                                listInexistentes.Add(item);
                            }
                        }
                    }
                    else if (listaVerificarEquip != null)
                    {
                        foreach (Equipamento equip in listaVerificarEquip)
                        {
                            if ((dt.Select("" + coluna + " = '" + equip.Codigo + "'")).Length != 0)
                            {
                                listInexistentes.Add(equip.Codigo);
                            }
                        }
                    }
                }
            }
            catch { throw; }

            return listInexistentes;
        }

        public List<string> VerificandoExistenciaEquipamentos(List<Equipamento> listEquipamentos)
        {
            return realizandoVerificacoes("equipamento", "cod_equipamento", null, listEquipamentos);
        }

        /// <summary>
        /// Responsável por criar os inserts com os registros
        /// </summary>
        /// <param name="dt">Datatable com os registros contidos no excel</param>
        public void InserindoNaBase(List<Equipamento> listEquipamento, string usuario)
        {
            try
            {
                StringBuilder sb = new StringBuilder();

                foreach (Equipamento item in listEquipamento)
                {
                    sb.AppendLine("INSERT INTO Equipamento(cod_equipamento, cod_tipo_equipamento, cod_local_equipamento, cod_empresa, desc_equipamento, ativado) ");
                    sb.AppendLine("VALUES ('" + item.Codigo + "', '" + item.Tipo + "', '" + item.Local + "', '001', '" + item.Descricao.Replace("'", "''") + "', 'True');");
                }

                string insertLog = "INSERT INTO LogImportacaoWeb VALUES('" + usuario + "', '" + DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + "', " + listEquipamento.Count + ");";

                using (TransactionScope scope = new TransactionScope())
                {
                    executarQuery(sb.ToString() + insertLog);
                    
                    scope.Complete();
                }
            }
            catch { throw; }
        }

        /// <summary>
        /// Método para efetuar a conexão com o banco de dados e executar a query passada por parâmetro
        /// </summary>
        /// <param name="query">string com a query a ser executada no banco de dados</param>
        /// <returns>Tabela com as informações recuperadas</returns>
        private DataTable executarQuery(string query)
        {
            DataTable dt = new DataTable();
            SqlConnection conn = new SqlConnection(strConn);

            try
            {
                SqlCommand command = new SqlCommand(query, conn);
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                adapter.Fill(dt);
            }
            catch { throw; }
            finally { conn.Close(); }

            return dt;
        }
    }
